package sk.vrto.service.dao.inmemory;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import sk.vrto.domain.Contact;
import sk.vrto.domain.ContactCreation;
import sk.vrto.domain.User;
import sk.vrto.service.dao.ContactRepository;
import sk.vrto.service.domain.ContactCreator;

import java.util.Arrays;
import java.util.Collection;

/**
 * ContactRepository that stores all the contacts directly in memory.
 * Repository existence is bound to the application lifecycle.
 */
public class InMemoryContactRepository implements ContactRepository {

    private Multimap<User, Contact> contacts = ArrayListMultimap.create();
    private final ContactCreator contactCreator;

    public InMemoryContactRepository(ContactCreator contactCreator) {
        this.contactCreator = contactCreator;
    }

    /**
     * Creates dummy contacts in memory
     * @param user User to create contacts for
     */
    public void initForUser(User user) {
        contacts.putAll(user, Arrays.asList(
                new Contact("Chuck Norris", "gmail@chucknorris.com", user),
                new Contact("Wayne Gretzky", "gretzky@nhl.com", user),
                new Contact("Mario Lemieux", "lemieux@nhl.com", user),
                new Contact("Arnold Schwarzenegger", "schwarzie@expedanbles.com", user),
                new Contact("James Gosling", "gosling@java.com", user),
                new Contact("Walter White", "walter.white@breakingbad.com", user),
                new Contact("Frank Horrigan", "bigbadboss@enclave.com", user),
                new Contact("Alex Ovechkin", "ovi8@caps.com", user)
        ));
    }

    @Override
    public Contact find(String email) {
        for (Contact contact : contacts.values()) {
            if (email.equals(contact.getEmail())) {
                return contact;
            }
        }
        return null;
    }

    @Override
    public Collection<Contact> load() {
        return contacts.values();
    }

    @Override
    public void insert(Contact contact) {
        contacts.put(contact.getUser(), contact);
    }

    @Override
    public void update(Contact contact) {
        for (Contact c : contacts.values()) {
            if (c.getEmail().equals(contact.getEmail())) {
                // only name can change
                c.setName(contact.getName());
            }
        }
    }

    @Override
    public void delete(Contact contact) {
        contacts.remove(contact.getUser(), contact);
    }

    @Override
    public Collection<Contact> loadContatsForUser(User user) {
        return contacts.get(user);
    }

    @Override
    public ContactCreation getOrCreate(String emailAddress, User forUser) {
        Contact found = null;
        boolean freshlyCreated = false;

        for (Contact contact : contacts.get(forUser)) {
            if (contact.getEmail().equals(emailAddress)) {
                found = contact;
                break;
            }
        }

        if (null == found) {
            found = contactCreator.mapFromAddress(emailAddress, forUser);
            insert(found);
            freshlyCreated = true;
        }

        return new ContactCreation(found, freshlyCreated);
    }
}
